package com.github.livebase.event;

import android.util.ArrayMap;

import com.github.livebase.log.Logger;
import com.github.livebase.util.base.CollectionsUtil;

import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName EventBus
 * @description:
 * @author: biao532
 * @create: 2023-12-20 17:44
 * @Version 1.0
 **/
public class SimpleEventBus implements EventBus, EventDispatcher.DestroyListener {
    private Map<String, EventDispatcher> dispatcherMap;

    private static ExecutorService executor;
    private Logger logger;
    public static ExecutorService getExecutor() {
        return executor;
    }

    private static volatile EventBus eventBus;

    public static void init(Logger logger, int threadCount) {
        synchronized (SimpleEventBus.class) {
            if (executor == null) {
                executor = Executors.newFixedThreadPool(threadCount);
                ((SimpleEventBus)getDefault()).setLogger(logger);
            }
        }
    }
    public static EventBus getDefault() {
        if (eventBus == null) {
            synchronized (SimpleEventBus.class) {
                if (null == eventBus) {
                    eventBus = new SimpleEventBus();
                }
            }
        }
        return eventBus;
    }

    private SimpleEventBus() {
        dispatcherMap = new ArrayMap<>();
    }
    private void setLogger(Logger logger) {
        this.logger = logger;
    }
    @Override
    public void publish(Event event) {
        getEventDispatcher(event.getEventId(), false).dispatch(event);
        if (Event.isEvent(event, EventBus.EVENT_APP_EXIT)) {
            CollectionsUtil.foreach(dispatcherMap.values(), (d)-> {
                d.destroy();
            });
            dispatcherMap.clear();
            if (executor != null) {
                executor.shutdown();
            }
        }
    }

    @Override
    public void register(String eventId, EventListener listener, boolean async) {
        getEventDispatcher(eventId, true).register(listener, async);
    }

    @Override
    public void unregister(String eventId, EventListener listener) {
        getEventDispatcher(eventId, false).unregister(listener);
    }

    private EventDispatcher getEventDispatcher(String eventId, boolean autoCreate) {
        if (dispatcherMap.containsKey(eventId)) {
            return dispatcherMap.get(eventId);
        }
        if (autoCreate) {
            EventDispatcherImpl eventDispatcherImpl = new EventDispatcherImpl(eventId, logger);
            eventDispatcherImpl.addDestroyListener(this);
            dispatcherMap.put(eventId, eventDispatcherImpl);
            return eventDispatcherImpl;
        }
        return EventDispatcherImpl.EMPTY;
    }

    @Override
    public void onDestroy(EventDispatcher dispatcher) {
        dispatcherMap.remove(dispatcher.getEventId());
    }
}
